
use std::{fmt::Display, path::PathBuf};

use clap::Parser;
use serde::{Deserialize, Serialize};
use wtask_base::{app::get_wtask_data_dir, cmd::{file_de_load, file_en_save}, logs::WTASK_BASIC_FILE_NAME, error::WResult, timer::TimerAppTrait};

use crate::{func::msg_func_none, task::utils::meta::{CmdArgs, TaskSubmitMeta}};



#[derive(Debug, Clone, Serialize, Deserialize, Parser)]
pub enum TimerApp {
    Cmd(CmdArgs),
    Task(TaskSubmitMeta),
}

impl TimerAppTrait for TimerApp {
    type Key = PathBuf;

    async fn save(self, name: &str, log: &[PathBuf]) -> WResult<()> {
        file_en_save(name, &(self, log), Some(("timer", false)))?;
        Ok(())
    }
    
    async fn load(f: &PathBuf) -> WResult<(TimerApp, Vec<PathBuf>)> {
        file_de_load(f, None, false)
    }

    async fn get_all_timer() -> WResult<Vec<PathBuf>> {
        let timer_all = get_wtask_data_dir("timer", false)?
            .read_dir()?
            .map(| v | {
                v.unwrap().path()
            }).collect::<Vec<_>>();

        Ok(timer_all)
    }

    fn timer_str(timer: &PathBuf) -> &str {
        timer.file_name().unwrap().to_str().unwrap().trim_end_matches(WTASK_BASIC_FILE_NAME).trim_matches('.')
    }

    async fn run(self) -> WResult<PathBuf> {
        let (exe, mut cmd_args) = match self {
            Self::Cmd(v) => (v.cmd[0].clone(), v),
            Self::Task(v) => (format!("{}@{}", v.app, v.version), v.try_into()?),
        };
        cmd_args.tag = format!("【定时】{}", cmd_args.tag);
        let r = cmd_args.run_cmd_task(exe, Box::new(msg_func_none))?;
        Ok(r.basic.dir_result)
    }

    fn get_cmd_and_args(self) -> (String, Vec<String>) {
        match self {
            TimerApp::Cmd(s) => (
                s.cmd.join(" "),
                s.envs
            ),
            TimerApp::Task(s) => (
                format!("{}@{}", s.app, s.version),
                s.args
            )
        }
    }

    fn get_note(&self) -> WResult<&str> {
        let r = match self {
            TimerApp::Cmd(v) => {
                v.note.as_str()
            },
            TimerApp::Task(v) => {
                // 参数检查：尝试将task参数解析为cmd参数
                let _: CmdArgs = v.clone().try_into()?;
                v.note.as_str()
            }
        };
        Ok(r)
    }
}

impl Display for TimerApp {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let t = match self {
            Self::Cmd(_) => "Cmd",
            Self::Task(_) => "Task",
        };
        write!(f, "{}", t)
    }
}
